
#include <stdio.h>
#include <stdlib.h> 
#include <unistd.h>  
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> 
#include <termios.h>
#include <errno.h>   
#include <limits.h> 
#include <asm/ioctls.h>
#include <time.h>
#include <pthread.h>
#include <termios.h>
#define DATA_LEN                0xFF                                    /* test data's len              */
#include <termios.h>
#include <string.h>
//#define DEBUG                 1

#include <linux/serial.h>


/*********************************************************************************************************
** Function name:           openSerial
** Descriptions:            open serial port at raw mod
** input paramters:         iNum        serial port which can be value at: 1, 2, 3, 4
** output paramters:        NONE
** Return value:            file descriptor
** Create by:               zhuguojun
** Create Data:             2008-05-19
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
static int openSerial(char *cSerialName,unsigned int bps)
{
    int iFd;
    struct termios opt; 
    iFd = open(cSerialName, O_RDWR | O_NOCTTY);                        
    if(iFd < 0) {
        perror(cSerialName);
        return -1;
    }

    tcgetattr(iFd, &opt);      
    cfsetispeed(&opt, bps);
    cfsetospeed(&opt, bps);

    /*
     * raw mode
     */
    opt.c_lflag   &=   ~(ECHO   |   ICANON   |   IEXTEN   |   ISIG);
    opt.c_iflag   &=   ~(BRKINT   |   ICRNL   |   INPCK   |   ISTRIP   |   IXON);
    opt.c_oflag   &=   ~(OPOST);
    opt.c_cflag   &=   ~(CSIZE   |   PARENB);
    opt.c_cflag   |=   CS8;

    /*
     * 'DATA_LEN' bytes can be read by serial
     */
    opt.c_cc[VMIN]   =   DATA_LEN;                                      
    opt.c_cc[VTIME]  =   150;

    if (tcsetattr(iFd,   TCSANOW,   &opt)<0) {
        return   -1;
    }


    int portfd;
    #if (__GNUC__ == 4 && __GNUC_MINOR__ == 3)
	struct my_serial_rs485 rs485conf;
	struct my_serial_rs485 rs485conf_bak;
    #else
    	struct serial_rs485 rs485conf;
    	struct serial_rs485 rs485conf_bak;
    #endif
    

    portfd=iFd;
    /* Driver-specific ioctls: ...\linux-3.10.x\include\uapi\asm-generic\ioctls.h */
    #define TIOCGRS485      0x542E
    #define TIOCSRS485      0x542F
    if (ioctl (portfd, TIOCGRS485, &rs485conf) < 0) 
	{
		/* Error handling.*/ 
		// Log::Inf("ioctl TIOCGRS485 error.\n");
        printf( "[ERR] ioctl TIOCGRS485 error.\n");
	}
	/* Enable RS485 mode: */
	rs485conf.flags |= SER_RS485_ENABLED;

	/* Set logical level for RTS pin equal to 1 when sending: */
	rs485conf.flags |= SER_RS485_RTS_ON_SEND;
	//rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;

	/* set logical level for RTS pin equal to 0 after sending: */ 
	rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
	//rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);



	/* Set rts delay after send, if needed: */
	rs485conf.delay_rts_after_send = 0x80;

	if (ioctl (portfd, TIOCSRS485, &rs485conf) < 0)
	{
		/* Error handling.*/ 
		printf("ioctl TIOCSRS485 error.\n");
        
	}

	if (ioctl (portfd, TIOCGRS485, &rs485conf_bak) < 0)
	{
		/* Error handling.*/ 
		printf("ioctl TIOCGRS485 error.\n");
    }
    else
    {
        printf("Config Rs485 Ok.\n");
    }
    return iFd;
}

int main(int argc, char** argv) 
{
	char tmp[1024];
	int len;
	int fd, i;


    printf("Usage: %s [ -s serial port  -b baund]  \n",argv[0]);
    printf("It put byte +1 which it read,for example: read 0x01,put 0x02  \n",argv[0]);


    unsigned char uart_port[100]={"/dev/ttymxc1"};
    int bps=0;
    unsigned int   baudRate= B9600;

    int  opt;
    while ((opt=getopt(argc,argv,"p:s:b:?")) != -1)
    {
        switch (opt)
        {
        case 's':
            memset(uart_port,0,sizeof(uart_port));
            strncpy(uart_port,optarg,99);
            break;
        case 'b':
            bps = atoi(optarg);
            break;
        default: /* '?' */
                   fprintf(stderr, "Usage: %s [-p port -s serial port  -b baund]  \n",
                           argv[0]);
                   exit(EXIT_FAILURE);
        }
    }
    switch(bps)
    {
        case 4800:
            baudRate=B4800;
            break;
        case 19200:
            baudRate=B19200;
            break;
        case 38400:
            baudRate=B38400;
            break;
        case 57600:
            baudRate=B57600;
            break;
        case 115200:
            baudRate=B115200;
            break;
        default:
            baudRate=B9600;
            bps=9600;
            break;
    }


    printf("set uartport is %s\n",uart_port);
    printf("set uartspeed is %d\n",bps);

	fd = openSerial(uart_port,baudRate);

	for(i = 0; i < 16; i++) 
		tmp[i] = i%0xFF;

    printf("write 16 byte from 0x00 to 0x15 \n",uart_port);
	write(fd, tmp, 16);

	while (1) {
		len = read(fd, tmp, 0x01);	
		for(i = 0; i < len; i++)
			printf("%x", tmp[i]++);
         write(fd, tmp, len);
		printf("\n");
	}
}
